package com.poetry.service.impl;

import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.poetry.domain.dto.PoemDTO;
import com.poetry.service.IHistoryService;
import com.poetry.service.ISearchService;
import lombok.extern.slf4j.Slf4j;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.poetry.constant.RedisConstant;
import com.poetry.domain.po.Poem;
import com.poetry.exception.BasePage;
import com.poetry.exception.R;
import com.poetry.mapper.PoemMapper;
import com.poetry.service.IPoemService;
import com.poetry.util.RedisUtil;
import com.poetry.util.UserContext;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class PoemServiceImpl extends ServiceImpl<PoemMapper, Poem>
        implements IPoemService {
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private ISearchService searchService;
    @Resource
    private IHistoryService historyService;

    @Override
    public R<List<Poem>> searchPoemPage(BasePage basePage) {
        // 页码
        int pageNum = basePage.getPageNum();
        // 页数
        int pageSize = basePage.getPageSize();
        // 内容
        String query = basePage.getQuery();
        // 条件
        String condition = basePage.getCondition();
        Page<Poem> pageInfo = new Page<>(pageNum, pageSize);
        if (StrUtil.isBlank(condition) || StrUtil.isBlank(query)) {
            LambdaQueryWrapper<Poem> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.orderByAsc(Poem::getId);
            Page<Poem> page = this.page(pageInfo, queryWrapper);
            if (page.getTotal() == 0) {
                return R.error("诗词列表为空");
            }
            List<Poem> records = page.getRecords();
            records.forEach(this::isPoemLiked);
            return R.success("获取诗词列表成功", records);
        }
        QueryWrapper<Poem> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.like(condition, query);
        List<Poem> records = getRecords(pageInfo, queryWrapper1);
        if (records.isEmpty()) {
            return R.error("获取诗词列表为空");
        }
        return R.success("获取诗词列表成功", records);
    }

    private List<Poem> getRecords(Page<Poem> pageInfo, QueryWrapper<Poem> queryWrapper) {
        Page<Poem> page = this.page(pageInfo, queryWrapper);
        List<Poem> records = page.getRecords();
        records.forEach(this::isPoemLiked);
        return records;
    }

    @Override
    public R<Poem> queryById(Integer id) {
        Poem poem = redisUtil.queryWithPassThrough(RedisConstant.CACHE_POEM_KEY, id, Poem.class,
                this::getById, RedisConstant.CACHE_POEM_TTL, TimeUnit.MINUTES);
        if (poem == null) {
            return R.error("诗词不存在");
        }
        isPoemLiked(poem);
        historyService.addHistory(id);
        return R.success("查询诗词信息成功", poem);
    }

    private void isPoemLiked(Poem poem) {
        Integer userId = UserContext.getUserId();
        if (userId == null) {
            return;
        }
        String key = RedisConstant.POEM_LIKED_KEY + userId;
        Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, poem.getId().toString());
        poem.setIsLike(BooleanUtil.isTrue(isMember));
    }

    @Override
    public R<String> likePoem(Integer id) {
        Integer userId = UserContext.getUserId();
        if (userId == null) {
            return R.error("用户未登录");
        }
        String key = RedisConstant.POEM_LIKED_KEY + userId;
        Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, id.toString());
        if (BooleanUtil.isFalse(isMember)) {
            boolean isSuccess = update().setSql("liked = liked + 1")
                    .eq("id", id).update();
            if (isSuccess) {
                stringRedisTemplate.opsForSet().add(key, id.toString());
            }
        } else {
            boolean isSuccess = update().setSql("liked = liked - 1")
                    .eq("id", id).update();
            if (isSuccess) {
                stringRedisTemplate.opsForSet().remove(key, id.toString());
            }
        }
        return R.success(null, "收藏成功");
    }

    @Override
    public R<List<Poem>> queryLikedPoem() {
        Integer userId = UserContext.getUserId();
        if (userId == null) {
            return R.error("用户未登录");
        }
        String key = RedisConstant.POEM_LIKED_KEY + userId;
        Set<String> value = stringRedisTemplate.opsForSet().members(key);
        if (value == null || value.isEmpty()) {
            return R.error("收藏列表为空");
        }
        List<Integer> ids = value.stream().map(Integer::valueOf).toList();
        String idStr = StrUtil.join(",", ids);
        List<Poem> Poems = this.query()
                .in("id", ids)
                .last("ORDER BY FIELD(id," + idStr + ")").list();
        return R.success("收藏列表获取成功", Poems);
    }

    @Override
    public R<Poem> setCategory(PoemDTO poemDTO) {
        Integer poemId = poemDTO.getId();
        List<String> categoryList = poemDTO.getCategory();
        Poem poem = this.getById(poemId);
        if (poem == null) {
            return R.error("诗词不存在");
        }
        String categories = StrUtil.join(",", categoryList);
        poem.setCategories(categories);
        boolean isSuccess = this.updateById(poem);
        if (!isSuccess) {
            return R.error("诗词类别设置失败");
        }
        return R.success("诗词类别设置成功", poem);
    }

    @Override
    @Transactional
    public R<String> addPoem(Poem poem) {
        if (poem.getTitle() == null || StringUtils.isBlank(poem.getTitle())) {
            return R.error("诗词标题不能为空");
        }
        if (poem.getDynasty() == null || StringUtils.isBlank(poem.getDynasty())) {
            return R.error("诗词朝代信息不能为空");
        }
        if (poem.getContent() == null || StringUtils.isBlank(poem.getContent())) {
            return R.error("诗词内容不能为空");
        }
        if (poem.getAuthor() == null || StringUtils.isBlank(poem.getAuthor())) {
            return R.error("诗词作者信息不能为空");
        }
        boolean isSuccess = this.save(poem);
        if (!isSuccess) {
            return R.error("诗词信息添加失败");
        }
        poem = this.getOne(query()
                .eq("title", poem.getTitle())
                .eq("dynasty", poem.getDynasty())
                .eq("author", poem.getAuthor()));
        if (poem == null) {
            return R.error("添加诗词信息失败");
        }
        searchService.addOrUpdatePoem(poem);
        return R.success(null, "诗词信息添加成功");
    }

    @Override
    @Transactional
    public R<Poem> updatePoem(Poem poem) {
        if (poem.getTitle() == null || StringUtils.isBlank(poem.getTitle())) {
            return R.error("诗词标题不能为空");
        }
        if (poem.getDynasty() == null || StringUtils.isBlank(poem.getDynasty())) {
            return R.error("诗词朝代信息不能为空");
        }
        if (poem.getContent() == null || StringUtils.isBlank(poem.getContent())) {
            return R.error("诗词内容不能为空");
        }
        if (poem.getAuthor() == null || StringUtils.isBlank(poem.getAuthor())) {
            return R.error("诗词作者信息不能为空");
        }
        if (this.getById(poem.getId()) == null) {
            return R.error("诗词不存在");
        }
        boolean isSuccess = this.updateById(poem);
        if (!isSuccess) {
            return R.error("诗词信息添加失败");
        }
        searchService.addOrUpdatePoem(poem);
        stringRedisTemplate.delete(RedisConstant.CACHE_POEM_KEY + poem.getId());
        return R.success("诗词信息添加成功", poem);
    }

    @Override
    @Transactional
    public R<String> deleteBatchByIds(List<Integer> ids) {
        boolean isSuccess = this.removeByIds(ids);
        if (!isSuccess) {
            return R.error("删除失败");
        }
        searchService.deletePoem(ids);
        stringRedisTemplate.delete(RedisConstant.CACHE_POEM_KEY + ids);
        return R.success(null, "删除成功");
    }
}
